using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;
using Microsoft.Xna.Framework.Content;
using Arcadium.Graphics;
using Arcadium.Screens.Menus.MenuHelpers;

namespace Arcadium.Graphics
{
    class View : DrawableGameComponent
    {
        #region Fields

        // Ideal dimensions
        private static int preferredScreenWidth = 1920;
        private static int preferredScreenHeight = 1080;

        // The View object that takes care of this games rendering
        private static View singletonInstance;

        // Graphics object asigned with this View
        private GraphicsDeviceManager graphics;

        // The ScreenManager that holds the screen we're drawing
        private ScreenManager screenManager;

        #endregion

        #region Properties

        /// <summary>
        /// Gets the preferred screen width of this game.
        /// </summary>
        public static int ScreenWidth
        {
            get { return preferredScreenWidth; }
        }

        /// <summary>
        /// Gets the screen width of this game.
        /// </summary>
        public static int ActualScreenWidth
        {
            get { return singletonInstance.GraphicsDevice.Viewport.Width; }
        }

        /// <summary>
        /// Gets the preferred screen height of this game.
        /// </summary>
        public static int ScreenHeight
        {
            get { return preferredScreenHeight; }
        }

        /// <summary>
        /// Gets the actual screen height of this game.
        /// </summary>
        public static int ActualScreenHeight
        {
            get { return singletonInstance.GraphicsDevice.Viewport.Height; }
        }

        /// <summary>
        /// A rectangle describing the whole drawing area.
        /// </summary>
        public static Rectangle ScreenRect { 
            get { return new Rectangle(0, 0, ActualScreenWidth, ActualScreenHeight); } 
        }

        /// <summary>
        /// Most art is designed for 1920*1080. Scale by this to make it look nice anyway.
        /// </summary>
        public static Vector2 ScreenScale
        {
            get 
            {
                if (!screenScale.HasValue)
                    screenScale = new Vector2(ActualScreenWidth, ActualScreenHeight) / new Vector2(preferredScreenWidth,
                        preferredScreenHeight);
                return screenScale.Value;
            }
        }

        private static Vector2? screenScale = null;

        #endregion

        #region Initialization

        /// <summary>
        /// Constructs a new view component.
        /// </summary>
        private View(ScreenManager screenManager)
            : base(screenManager.Game)
        {
            this.screenManager = screenManager;
            graphics = new GraphicsDeviceManager(screenManager.Game);
#if !XBOX
            //graphics.IsFullScreen = true;
#endif

            graphics.PreferredBackBufferWidth = preferredScreenWidth;
            graphics.PreferredBackBufferHeight = preferredScreenHeight;
        }

        /// <summary>
        /// Creates the view component.
        /// </summary>
        public static void Create(ScreenManager screenManager)
        {
            if (singletonInstance == null)
            {
                singletonInstance = new View(screenManager);
                screenManager.Game.Components.Add(singletonInstance);
            }
        }

        public static View GetInstance()
        {
            return singletonInstance;
        }

        /// <summary>
        /// Load your graphics content.
        /// </summary>
        protected override void LoadContent()
        {
            // Load content belonging to the screen manager.
            ContentManager content = Game.Content;

            // Create a SpriteBatch object
            ViewResource.SpriteBatch = new SpriteBatch(graphics.GraphicsDevice);

            // Shared graphics resources
            ViewResource.MenuFont = content.Load<SpriteFont>("Fonts\\menufont");
            ViewResource.BlankTexture = content.Load<Texture2D>("blank");

            // Tell each of the screens to load their content.
            foreach (GameScreen screen in screenManager.GetScreens())
            {
                screen.LoadContent();
            }
            base.LoadContent();
        }

        /// <summary>
        /// Unload your graphics content.
        /// </summary>
        protected override void UnloadContent()
        {
            // Tell each of the screens to unload their content.
            foreach (GameScreen screen in screenManager.GetScreens())
            {
                screen.UnloadContent();
            }
        }

        #endregion
        
        #region Draw

        /// <summary>
        /// Gets the renderdata from the screenmanager
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.Black);

            foreach (GameScreen screen in screenManager.GetScreens())
            {
                if (screen.ScreenState == ScreenState.Hidden)
                    continue;

                screen.Draw(gameTime);
            }
            base.Draw(gameTime);
        }

        /// <summary>
        /// Helper draws a translucent black fullscreen sprite, used for fading
        /// screens in and out, and for darkening the background behind popups.
        /// </summary>
        public void FadeBackBufferToBlack(float alpha)
        {
            SpriteBatch spriteBatch = ViewResource.SpriteBatch;
            spriteBatch.Begin();
            spriteBatch.Draw(ViewResource.BlankTexture,
                             ScreenRect,
                             Color.Black * alpha);
            spriteBatch.End();
        }

        #endregion

        #region Methods

        public static Vector2 Adjust(Vector2 vector)
        {
            return vector * ScreenScale;
        }

        public static SpriteEffects ToEffect(int direction)
        {
            return (SpriteEffects)(direction / 2f + .5);
        }

        #endregion

    }
}
